use std::collections::*;
use std::hash::Hash;

/// Checks if the iterator contains any duplicate items.  Uses memory linear in
/// the length of the iterator.  Returns the item if it exists.
pub fn check_dups<C: Eq + Hash, I: Iterator<Item = C>>(iter: I) -> Option<C> {
    check_dups_by(iter, |e| e)
}

/// Passes a fn over items in the iterator to extract a property and checks if
/// there's any duplicates according to the view.
pub fn check_dups_by<T: Eq + Hash, C, I: Iterator<Item = C>, F: Fn(C) -> T>(
    iter: I,
    f: F,
) -> Option<T> {
    let mut set = HashSet::new();

    for e in iter {
        let ee = f(e);
        if set.contains(&ee) {
            return Some(ee);
        }
        set.insert(ee);
    }

    None
}
